package main;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.TimerTask;

import javax.swing.*;
import jobs.*;
import spells.*;
import creatures.*;


public class GridTest extends JFrame{

	/* Initialize main variables used by GridTest, including Grid used, active player, active enemy and test variables
	 * Set position of starting characters
	 */
	ArrayList <String> history = new ArrayList<String>();
	JTextArea textArea = new JTextArea(10, 50);
	
	Grid currentGrid;
	Creature wolf = new Wolf(1,2,"michael");
	Creature wolf2 = new Wolf(3,2,"michael2");
	Player you = new Player(5,5,"Hero",new Reaper());
	double timeUntilNextAct = 0;//this stays probably
	double eTimeUntilNextAct = 0;//this stays probably
	//combat variables (some for testing only)
	Creature enemy;
	int weaponDamage;
	double attackSpeed;
	Timer gridTimer;
	//Cell currentCell;//contains what cell has last been clicked
	//all becomes Character.health, Character.strength etc
	
	
	int eCurHealth;
	int eMaxHealth;
	int eStrength;
	int eWeaponDamage;
	int eLevel;
	int eArmor;
	double eAttackSpeed;
	//all becomes Creature.health, Creature.strength etc
	//
	//contains list of creatures for multiple enemies
	ArrayList<Creature> creatures = new ArrayList<Creature>();
	//panel for drawing images
	TestingPanel currentPanel;
	
	static int ROWS = 12;
	static int COLUMNS = 16;
	//array labels for icons - uses special ImageLabel class instead of JLabel to store coordinates
	ImageLabel [][] labels = new ImageLabel[ROWS][COLUMNS];
	static int WIDTH = 824;
	static int HEIGHT = 646;
	public GridTest (){
		//DALTON - initialize player, enemy health
		you.curHealth = 100;
		you.maxHealth = 100;
		you.strength = 10;
		you.addSpell(new Fireball(you));
		you.addSpell(new Heal(you));
		you.addSpell(new Ignite(you));
		you.addSpell(new Replenish(you));
		Weapon dagger = new Weapon();
		dagger.damage = 5;
		dagger.attackSpeed = 0.5;
		you.weapon1 = dagger;
		you.level = 1;
		you.armor = 0;


		creatures.add(wolf);
		creatures.add(wolf2);

		//note by ben: 8 = rows, 6 = columns
		Grid grid1 = new Grid(COLUMNS,ROWS);
		currentGrid = grid1;
		//place occupants in Grid - is also needed in addition to characters grid method
		grid1.putOccupant(5, 5, you);
		grid1.putOccupant(1, 2, wolf);
		grid1.putOccupant(3, 2, wolf2);


		Dimension d = new Dimension (WIDTH,HEIGHT);
		this.setSize(d);
		/*this.setMaximumSize(d);
        this.setMinimumSize(d);*/

		//setLayout(new BoxLayout(this,BoxLayout.Y_AXIS));
		//this.setLayout(new BorderLayout());

		//setLayout(new BoxLayout(getContentPane(),BoxLayout.Y_AXIS));
		setLayout(new BorderLayout());
		//this.setLayout(new GridLayout(2,1));

		currentPanel = new TestingPanel(WIDTH, HEIGHT);
		
		currentPanel.currentCell=you.host;

		//currentPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
		add(currentPanel,BorderLayout.NORTH);

		ConsolePanel cPanel = new ConsolePanel();

		//cPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
		add(cPanel,BorderLayout.SOUTH);

		textArea.append("test!");
		textArea.append("\nlol");
		this.setVisible(true);
		this.setResizable(false);
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
	
		
		//timer for repainting of images - also can slow user input down if interval is bad; could use improvement
		
		gridTimer = new Timer(20,new ActionListener() {
			  // This is how you define an anonymous inner class
			  public void actionPerformed(ActionEvent e) {
			    if (creatures.size() > 0)
			    	combat(creatures);
			  }
			});
		gridTimer.start();
	}

	public static void main(String[] args) {
		GridTest t = new GridTest();

		//this.drawGrid();
	}
	
	//Dalton/Richard - method called when creatures exist in grid - manages turns and combat between main character
	//and enemies, takes ArrayList of enemies as parameter
	public void combat(ArrayList <Creature> creatures){
		Creature enemy = creatures.get(0);
		weaponDamage = you.weapon1.damage;
		attackSpeed = you.weapon1.attackSpeed;
		//all becomes Character.health, Character.strength etc
		
		eCurHealth = creatures.get(0).curHealth;
		eMaxHealth = creatures.get(0).maxHealth;
		eStrength = creatures.get(0).strength;
		eWeaponDamage = creatures.get(0).weapon1.damage;
		eLevel = creatures.get(0).level;
		eArmor = creatures.get(0).armor;
		eAttackSpeed = creatures.get(0).weapon1.attackSpeed;
		//all becomes Creature.health, Creature.strength etc
				
	
		int flag = 0;
		int damage = 0;
			if (flag == 0 && creatures.size()!=0)
			{
				if (timeUntilNextAct <= 0) //USER ACTION
				{
					
				}
				//other actions can include: spells, MOVING (should take a set time, ex: 0.5)
	
				else if (eTimeUntilNextAct <= 0)//ENEMY ACTION. must make work for multi enemies later
				{
					if (currentGrid.getDToEnemy(enemy) > 1) {
						wolf.ai(wolf,you);
						wolf2.ai(wolf2,you);
						eTimeUntilNextAct += 0.5;
					}
					else {
						damage = Player.attackDamage(eStrength,eWeaponDamage,eLevel,you.armor);
						System.out.println("Enemy attacks you for " + damage + " damage.");
						you.curHealth = you.curHealth - damage;
						System.out.println("Your Health is now: " + you.curHealth + "/" + you.maxHealth);
						eTimeUntilNextAct = eTimeUntilNextAct + eAttackSpeed;
					}
					
				}//right now only chooses to attack, enemy may use other actions later.
				//other actions can include: spells, MOVING (should take a set time, ex: 0.5)
				//AI: move towards player if player is not adjacent
				
				else //ITERATES TIME STEP
				{
					timeUntilNextAct = timeUntilNextAct - 0.1;
					eTimeUntilNextAct = eTimeUntilNextAct - 0.1;
					
					for (int i=0; i < you.buffs.size(); i++)
					{
						if (you.buffs.get(i) instanceof DoT)
						{
							DoT temp = (DoT)(you.buffs.get(i));
							if (temp.getTimeSinceTick() >= temp.getTickTime())
							{
								//DO THE DAMAGE
								you.curHealth+= temp.getDamage();
								System.out.print(you.name + " changes " + temp.getDamage() + " damage from " + temp.getName());
								temp.setTimeSinceTick(temp.getTimeSinceTick()-temp.getTickTime());
							}
							
							temp.setTimeSinceTick(temp.getTimeSinceTick() + 0.1);
						}
					}//checks DoT ticks for player
					
					for (int i=0; i < wolf.buffs.size(); i++)
					{
						if (wolf.buffs.get(i) instanceof DoT)
						{
							DoT temp = (DoT)(wolf.buffs.get(i));
							if (temp.getTimeSinceTick() >= temp.getTickTime())
							{
								//DO THE DAMAGE
								wolf.curHealth+= temp.getDamage();
								System.out.print(wolf.name + " changes " + temp.getDamage() + " damage from " + temp.getName());
								temp.setTimeSinceTick(temp.getTimeSinceTick()-temp.getTickTime());
								
								
								//boolean flag2=wolf.checkDeath();
								//if(flag2){
								//	System.out.println(wolf.name+" has died");
								//	you.gainXP(((Enemy)wolf).experience, ((Enemy)wolf).level);
								//	creatures.remove(wolf);
								//	currentCell.occ1=null;
								//}
							}
							
							temp.setTimeSinceTick(temp.getTimeSinceTick() + 0.1);
						}
					}//Make it work for n number of creatures eventually.
					
					for (int i=0; i < wolf2.buffs.size(); i++)
					{
						if (wolf2.buffs.get(i) instanceof DoT)
						{
							DoT temp = (DoT)(wolf2.buffs.get(i));
							if (temp.getTimeSinceTick() >= temp.getTickTime())
							{
								//DO THE DAMAGE
								wolf2.curHealth+= temp.getDamage();
								System.out.print(wolf2.name + " changes " + temp.getDamage() + " damage from " + temp.getName());
								temp.setTimeSinceTick(temp.getTimeSinceTick()-temp.getTickTime());
							}
							
							temp.setTimeSinceTick(temp.getTimeSinceTick() + 0.1);
							
						}
					}//Make it work for n number of creatures eventually.
					
					
				}//iterates time step. allow dots to tick etc.
	
				if (you.curHealth <= 0)
				{
					System.out.println("You have died!");
					flag = 1;
				}
				else if (eCurHealth <= 0)
				{
					System.out.println("You have defeated enemy!");
					flag = 1;
				}
			
				currentPanel.fillOccImages();
		}
	}

	//Richard: controls creature commands - how creature will follow human around the grid.  Method called
	//in combat method


	//controls user input - user input only works if it is the user's turn, problems MAY occur due to thread conflicts
	
	/*public class TestingPanel extends JPanel implements MouseListener, KeyListener{
		
		public TestingPanel(){
			//note by ben: GridLayout(x,y) where x = rows, y = columns
			this.setLayout(new GridLayout(ROWS,COLUMNS));
			Dimension d = new Dimension (WIDTH,HEIGHT);
			this.setSize(d);
			this.setPreferredSize(d);
			this.setMaximumSize(d);
			this.setMinimumSize(d);
			this.addKeyListener(this);
			Dimension label = new Dimension(50,50);
			fillOccImages();
		}
		//assumes all occupants have images assigned - fills in labels with appropriate images and combines 
		//terrain images with creature images
		public void fillOccImages(){
			//row (i)
			for (int i=ROWS-1;i>=0;i--){
				//column (j) 
				for (int j=0;j<COLUMNS;j++){
					//System.out.println("i/row: " + i + ", j/column: " + j);
					//different things if there is a creature image or not in the current cell
					if (currentGrid.cellGrid[j][i].hasOccupant()){
						BufferedImage cellImage = new BufferedImage(50,50,BufferedImage.TYPE_INT_ARGB);
						Graphics2D stuff = (Graphics2D)cellImage.getGraphics();
						MediaTracker track = new MediaTracker(this);
						String occImgString = currentGrid.cellGrid[j][i].getOccImage();
						String terrImgString = currentGrid.cellGrid[j][i].getTerrImage();
						Image occImage = Toolkit.getDefaultToolkit().getImage(occImgString);
						track.addImage(occImage, 1);
						Image terrImage = Toolkit.getDefaultToolkit().getImage(terrImgString);
						track.addImage(terrImage, 0);


						try {
							track.waitForAll();
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
						stuff.drawImage(terrImage,0,0,null);
						stuff.drawImage(occImage,0,0,null);
						if (labels[i][j] == null)
							labels[i][j] = new ImageLabel(i+","+j, new ImageIcon (cellImage), j, i);
						else
							labels[i][j].setIcon(new ImageIcon (cellImage));
					}
					else {
						BufferedImage cellImage = new BufferedImage(50,50,BufferedImage.TYPE_INT_ARGB);
						Graphics2D stuff = (Graphics2D)cellImage.getGraphics();
						MediaTracker track = new MediaTracker(this);
						String terrImgString = currentGrid.cellGrid[j][i].getTerrImage();
						Image terrImage = Toolkit.getDefaultToolkit().getImage(terrImgString);
						track.addImage(terrImage, 0);
						try {
							track.waitForAll();
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
						stuff.drawImage(terrImage,0,0,null);
						//if label never initialized create new imagelabel, else simply replace imagelabel image with terrain
						if (labels[i][j] == null)
							labels[i][j] = new ImageLabel(i+","+j, new ImageIcon (cellImage), j,i);
						else {
							labels[i][j].setIcon(new ImageIcon (cellImage));
							labels[i][j].setCoords(j, i);
						}
					}

				}
			}
			setLabelsToPanel();
		}
		
		//places imagelabels from array into JPanel and adds mouselistener - ensures only one mouselistener is added to avoid
		//problems
		public void setLabelsToPanel(){
			this.removeAll();
			for (int i=ROWS-1;i>=0;i--){
				//column
				for (int j=0;j<COLUMNS;j++){
					add(labels[i][j]);
					if (labels[i][j].getMouseListeners().length < 1)
					labels[i][j].addMouseListener(this);
				}
			}
		}
	
		public void mouseClicked(MouseEvent e) {
			ImageLabel i = (ImageLabel)e.getSource();
			
			currentCell=currentGrid.cellGrid[i.x][i.y];
			
			System.out.println("this is the pos of the label u clickxted: x:" + i.x + " y:" + i.y);
		}
		public void mouseEntered(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}
		public void mouseExited(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}
		public void mousePressed(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}
		public void mouseReleased(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}
		
		public void keyPressed(KeyEvent e) 
		{
			int code = e.getKeyCode();
			System.out.println(code);
			if (code == KeyEvent.VK_UP || code == KeyEvent.VK_DOWN || code == KeyEvent.VK_LEFT || code == KeyEvent.VK_RIGHT || code == KeyEvent.VK_A || code==KeyEvent.VK_1 || code==KeyEvent.VK_2 || code==KeyEvent.VK_3 || code==KeyEvent.VK_4){
				if (timeUntilNextAct <= 0){
					if (code == KeyEvent.VK_UP)
					{
						currentGrid.getPC().moveUp();
						timeUntilNextAct += 0.5;
					}//en else if
					else if (code == KeyEvent.VK_DOWN)
					{
						currentGrid.getPC().moveDown();
						timeUntilNextAct += 0.5;
					}//end else if
					else if (code == KeyEvent.VK_LEFT)
					{
						currentGrid.getPC().moveLeft();
						timeUntilNextAct += 0.5;
					}//end else if
					else if (code == KeyEvent.VK_RIGHT)
					{
						currentGrid.getPC().moveRight();
						timeUntilNextAct += 0.5;
					}//end else if
					else if(code==KeyEvent.VK_1){
						//System.out.println("REACHED;");
						Spell temp=you.findSpell("Fireball");
						temp.setTarget((Creature) currentCell.occ1);
						String cast = temp.applySpell(currentGrid);
						temp.setTarget(null);
						System.out.println(cast);
						System.out.println(currentCell.occ1.name+" Health is now: " + ((Creature)(currentCell.occ1)).curHealth + "/" + eMaxHealth);
						timeUntilNextAct = timeUntilNextAct + temp.getCastTime();
						boolean flag=((Creature) currentCell.occ1).checkDeath();
						if(flag){
							System.out.println(currentCell.occ1.name+" has died");
							you.gainXP(((Enemy)(currentCell.occ1)).experience,((Enemy)(currentCell.occ1)).level );

							creatures.remove(currentCell.occ1);
							currentCell.occ1=null;
						}
					}
				
				else if(code==KeyEvent.VK_2){
					Spell temp=you.findSpell("Heal");
					String cast = temp.applySpell(currentGrid);
					System.out.println(cast);
					System.out.println(you.name+"'s health is now "+you.curHealth+"/"+you.maxHealth);
					timeUntilNextAct = timeUntilNextAct + temp.getCastTime();
				}//end else if
				else if(code==KeyEvent.VK_3){
					Spell temp=you.findSpell("Ignite");
					temp.setTarget((Creature) currentCell.occ1);
					String cast = temp.applySpell(currentGrid);
					temp.setTarget(null);
					System.out.println(cast);
					System.out.println(currentCell.occ1.name+" Health is now: " + ((Creature)(currentCell.occ1)).curHealth + "/" + eMaxHealth);
					timeUntilNextAct = timeUntilNextAct + temp.getCastTime();
					boolean flag=((Creature) currentCell.occ1).checkDeath();
					if(flag){
						System.out.println(currentCell.occ1.name+" has died");
						you.gainXP(((Enemy)(currentCell.occ1)).experience, ((Enemy)(currentCell.occ1)).level);
						creatures.remove(currentCell.occ1);
						currentCell.occ1=null;
					}
				}//end else if
				else if(code==KeyEvent.VK_4){
					Spell temp=you.findSpell("Replenish");
					temp.setTarget((Creature) currentCell.occ1);
					String cast = temp.applySpell(currentGrid);
					temp.setTarget(null);
					System.out.println(cast);
					System.out.println(currentCell.occ1.name+" Health is now: " + ((Creature)(currentCell.occ1)).curHealth + "/" + eMaxHealth);
					timeUntilNextAct = timeUntilNextAct + temp.getCastTime();
					boolean flag=((Creature) currentCell.occ1).checkDeath();
					if(flag){
						System.out.println(currentCell.occ1.name+" has died");
						you.gainXP(((Enemy)(currentCell.occ1)).experience, ((Enemy)(currentCell.occ1)).level);
						creatures.remove(currentCell.occ1);
						currentCell.occ1=null;
					}
				}//end else if
				else if (code == KeyEvent.VK_A){
					Enemy temp=(Enemy)currentCell.occ1;
					if (!currentGrid.occupants.contains(currentCell)){
//						JOptionPane.showMessageDialog(null, "Sorry, but selected cell contains not an enemy.");
//						gridTimer.restart();
					}
					else if (currentGrid.getDToEnemy(temp) <= 1){
						
						int damage = Player.attackDamage(you.strength,weaponDamage,you.level,eArmor);
						System.out.println("You attack enemy for " + damage + " damage.");
						temp.takeDamage(damage);
						System.out.println("Enemy Health is now: " + temp.curHealth + "/" + eMaxHealth);
						timeUntilNextAct = timeUntilNextAct + attackSpeed;
						boolean flag=temp.checkDeath();
						if(flag){
							System.out.println("Enemy has died");
							you.gainXP(temp.experience, temp.level);
							creatures.remove(temp);
							wolf=null;
						}//end if
						timeUntilNextAct += 0.5;
					}//end if
					
				}//end else if

		//		currentPanel.fillOccImages();

			}//end if
				
		}//end if
			}//end if key is valid
		public void keyReleased(KeyEvent e) {
		}

		public void keyTyped(KeyEvent e) {
			// TODO Auto-generated method stub

		}
		public void actionPerformed(ActionEvent e) {
			// TODO Auto-generated method stub

		}
	}*/
	public class ConsolePanel extends JPanel{
		/* To be continued...
		 * 
		 */
		public ConsolePanel(){
			JScrollPane scrollPane = new JScrollPane(textArea);
			textArea.setEditable(false);
			this.add(scrollPane);
			Dimension d = new Dimension (824,20);
			this.setMaximumSize(d);
			this.setMinimumSize(d);
			this.setSize(d);
		}
		

		//		JTextField consoleTextArea = new JTextArea();
	}
	/* 
	 * Special labels with icons
	 */
	public class ImageLabel extends JLabel{
		int x;
		int y;
		public ImageLabel(String s, ImageIcon image, int x, int y){
			Dimension label = new Dimension(50,50);
			setMinimumSize(label);
			setMaximumSize(label);
			setSize(label);
			this.x = x;
			this.y = y;
			//setText(s);
			this.setIcon(image);
			//this.setText(labelT);
		}
		public void setCoords(int x, int y){
			this.x = x;
			this.y = y;
		}
	}

}
